﻿using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Nsf.Samples.RetryActivitySample.Infrastructure.Common.Commands;

namespace Nsf.Samples.RetryActivitySample.WorkflowBase.Activities
{
	public class ControlSequentialWorkflowActivity: SequentialWorkflowActivity
	{
        #region Dependency Properties

        public static readonly DependencyProperty CommandReceivedEvent =
            DependencyProperty.Register("CommandReceived",
                                        typeof(EventHandler<CommandReceivedEventArgs>),
                                        typeof(ControlSequentialWorkflowActivity));


        #endregion

        #region Events

        [Category("Handlers")]
        [Description("Please specify the method which will be called after control command received")]
        public event EventHandler<CommandReceivedEventArgs> CommandReceived
        {
            add { AddHandler(CommandReceivedEvent, value); }
            remove { RemoveHandler(CommandReceivedEvent, value); }
        }

        #endregion

        #region Constructor

        public ControlSequentialWorkflowActivity()
		{

        }

        public ControlSequentialWorkflowActivity(String name) : base(name)
        {

        }


        #endregion

        #region Internal Methods

        private void CreateWorkflowQueue(IComparable queueName, ActivityExecutionContext executionContext)
        {
            var workflowQueueService = executionContext.GetService<WorkflowQueuingService>();
            if (workflowQueueService == null)
                return;
            var queue = workflowQueueService.CreateWorkflowQueue(queueName, false);
            queue.QueueItemAvailable += OnQueueItemAvailable;
        }

        public void OnQueueItemAvailable(object sender, QueueEventArgs e)
        {
            var activityExecutionContext = (ActivityExecutionContext)sender;

            var workflowQueueService = activityExecutionContext.GetService<WorkflowQueuingService>();
            var workflowQueue = workflowQueueService.GetWorkflowQueue(e.QueueName);
            var commandData = workflowQueue.Dequeue() as CommandData;

            OnCommandReceived(activityExecutionContext, commandData);
        }

        private void OnCommandReceived(ActivityExecutionContext activityExecutionContext, CommandData commandData)
        {
            /*
            var invocationList = this.GetInvocationList<EventHandler<CommandReceivedEventArgs>>(CommandReceivedEvent);
            if (invocationList != null)
            {
                foreach (var handler in invocationList)
                {
                    handler(activityExecutionContext, new CommandReceivedEventArgs(commandData));
                }
            }
             */
            RaiseGenericEvent(CommandReceivedEvent, activityExecutionContext, new CommandReceivedEventArgs(commandData));
        }

        #endregion

        #region Overrides

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            CreateWorkflowQueue(WorkflowInstanceId, executionContext);
            return base.Execute(executionContext);
        }

        #endregion

    }

    [Serializable]
    public class CommandReceivedEventArgs : EventArgs
    {
        public CommandData Data { get; protected set; }

        public CommandReceivedEventArgs(CommandData commandData)
        {
            Data = commandData;
        }
    }

}
